package com.zhijian.medical.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.format.FastDateFormat;
import cn.hutool.core.util.NumberUtil;
import com.beust.jcommander.internal.Maps;
import com.google.common.collect.Lists;
import com.zhijian.medical.dao.local.MeetingRoomMapper;
import com.zhijian.medical.entity.po.MeetingAppointment;
import com.zhijian.medical.entity.po.MeetingRoom;
import com.zhijian.medical.entity.vo.request.MeetingAppointmentSearchVo;
import com.zhijian.medical.entity.vo.request.MeetingDataNewSaveOrUpdateVo;
import com.zhijian.medical.entity.vo.request.MeetingRoomApplyVo;
import com.zhijian.medical.entity.vo.request.MeetingRoomSearchVo;
import com.zhijian.medical.entity.vo.response.MeetingAppointmentVo;
import com.zhijian.medical.entity.vo.response.MeetingRoomDayVo;
import com.zhijian.medical.entity.vo.response.MeetingRoomMonthVo;
import com.zhijian.medical.entity.vo.response.MeetingRoomVo;
import com.zhijian.medical.enums.MeetingRoomHourEnum;
import com.zhijian.medical.service.MeetingAppointmentService;
import com.zhijian.medical.service.MeetingDataNewService;
import com.zhijian.medical.service.MeetingRoomService;
import com.zhijian.medical.util.AssertUtil;
import com.zhijian.medical.util.Page;
import com.zhijian.medical.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 会议室业务处理层
 *
 * @author HCG
 * @version: 1.0
 * @date 2023-09-26 09:57:34
 */
@Slf4j
@Service
public class MeetingRoomServiceImpl implements MeetingRoomService {

    @Autowired
    private MeetingRoomMapper mapper;

    @Autowired
    private MeetingAppointmentService meetingAppointmentService;

    @Autowired
    private MeetingDataNewService meetingDataNewService;

    @Override
    public MeetingRoom selectById(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public MeetingRoomVo selectVoById(Long id) {
        return mapper.selectVoById(id);
    }

    @Override
    public void deleteById(Long id) {
        mapper.deleteByPrimaryKey(id);
    }

    @Override
    public Long insert(MeetingRoom meetingRoom) {
        Date now = new Date();
        meetingRoom.setCreateTime(now);
        meetingRoom.setUpdateTime(now);
        return mapper.insert(meetingRoom) > 0 ? meetingRoom.getId() : 0L;
    }

    @Override
    public boolean update(MeetingRoom meetingRoom) {
        Date now = new Date();
        meetingRoom.setUpdateTime(now);
        return mapper.updateByPrimaryKey(meetingRoom) != 0;
    }

    @Override
    public boolean updateByPrimaryKeySelective(MeetingRoom record) {
        Date now = new Date();
        record.setUpdateTime(now);
        return mapper.updateByPrimaryKeySelective(record) != 0;
    }

    @Override
    public Integer count(MeetingRoomSearchVo meetingRoomSearchVo) {
        return mapper.count(meetingRoomSearchVo);
    }

    @Override
    public List<MeetingRoomVo> selectList(MeetingRoomSearchVo meetingRoomSearchVo) {
        return mapper.selectList(meetingRoomSearchVo);
    }

    @Override
    public Page<MeetingRoomVo> selectPage(MeetingRoomSearchVo meetingRoomSearchVo) {
        //先直接查总数
        int count = count(meetingRoomSearchVo);
        //分页
        Page<MeetingRoomVo> page = new Page<>(true, count, meetingRoomSearchVo.getPageNum(), meetingRoomSearchVo.getPageSize());
        meetingRoomSearchVo.setStartIndex(page.getStartIndex());
        page.setPage(true);
        page.setTotalCount(count);
        List<MeetingRoomVo> responseVos = this.selectList(meetingRoomSearchVo);
        page.setData(responseVos);
        return page;
    }

    @Override
    public boolean insertBatch(List<MeetingRoom> entities) {
        return CollectionUtil.isNotEmpty(entities) && mapper.insertBatch(entities) > 0;
    }

    @Override
    public List<MeetingRoomDayVo> selectMeetingRoomDayListByDay(String day) {
        //先查询出会议室
        List<MeetingRoomVo> meetingRoomVos = this.selectList(MeetingRoomSearchVo.builder().build());
        if (CollectionUtil.isNotEmpty(meetingRoomVos)) {
            return meetingRoomVos.stream().map(meetingRoomVo -> {
                MeetingRoomDayVo meetingRoomDayVo = new MeetingRoomDayVo();
                Byte openStartTime = meetingRoomVo.getOpenStartTime();
                Byte openEndTime = meetingRoomVo.getOpenEndTime();
                //范围
                int[] range = NumberUtil.range(openStartTime, openEndTime);
                List<Integer> ro = Lists.newLinkedList();
                Arrays.stream(range).forEach(ro::add);
                //可以预约的
                meetingRoomDayVo.setCanHours(ro);
                meetingRoomDayVo.setMeetingRoom(meetingRoomVo);
                //查询预约记录
                List<MeetingAppointmentVo> meetingAppointmentVos = meetingAppointmentService.selectList(MeetingAppointmentSearchVo.builder().roomId(meetingRoomVo.getId()).date(Integer.valueOf(day)).build());
                if (CollectionUtil.isNotEmpty(meetingAppointmentVos)) {
                    //所有的
                    List<String> allHous2 = Lists.newLinkedList();

                    List<MeetingRoomDayVo.SingleCellVo> singleCellVoList = Lists.newLinkedList();

                    for (MeetingAppointmentVo meetingAppointmentVo : meetingAppointmentVos) {
                        String hour = meetingAppointmentVo.getHour();
                        if (StringUtils.isNotBlank(hour)) {
                            List<String> hoursList = Arrays.asList(hour.split(","));
                            allHous2.addAll(hoursList);
                            for (String h : hoursList) {
                                MeetingRoomDayVo.SingleCellVo cellVo = new MeetingRoomDayVo.SingleCellVo();
                                cellVo.setHour(Integer.valueOf(h));
                                cellVo.setMeetingAppointmentVo(meetingAppointmentVo);
                                singleCellVoList.add(cellVo);
                            }
                        }
                    }
                    meetingRoomDayVo.setSingleCellList(singleCellVoList);
                    //已经预约的
                    meetingRoomDayVo.setApplyHours(allHous2.stream().map(Integer::valueOf).collect(Collectors.toList()));
                }
                return meetingRoomDayVo;
            }).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    @Override
    public List<MeetingRoomMonthVo> selectMeetingRoomMonthListByMonth(String month) {
        //先查询出会议室
        List<MeetingRoomVo> meetingRoomVos = this.selectList(MeetingRoomSearchVo.builder().build());
        DateTime thisMonth = DateUtil.parse(month, "yyyy-MM");
        DateTime monthBegin = DateUtil.beginOfMonth(thisMonth);
        DateTime monthEnd = DateUtil.endOfMonth(thisMonth);
        List<DateTime> dateTimes = DateUtil.rangeToList(monthBegin, monthEnd, DateField.DAY_OF_MONTH);
        if (CollectionUtil.isNotEmpty(meetingRoomVos)) {
            return meetingRoomVos.stream().map(meetingRoomVo -> {
                MeetingRoomMonthVo meetingRoomMonthVo = new MeetingRoomMonthVo();
                meetingRoomMonthVo.setMeetingRoomId(meetingRoomVo.getId());
                meetingRoomMonthVo.setMeetingRoomName(meetingRoomVo.getName());
                //查询预约记录
                List<MeetingAppointmentVo> meetingAppointmentVos = meetingAppointmentService.selectList(MeetingAppointmentSearchVo.builder().roomId(meetingRoomVo.getId()).month(DateUtil.format(thisMonth, "yyyyMM")).build());

                Map<Integer, List<MeetingAppointmentVo>> meetingAppMap = Maps.newHashMap();
                if (CollectionUtil.isNotEmpty(meetingAppointmentVos)) {
                    meetingAppMap = meetingAppointmentVos.stream().collect(Collectors.groupingBy(MeetingAppointmentVo::getDate));
                }

                List<MeetingRoomMonthVo.SingleCellVo> singleCellVoList = Lists.newLinkedList();
                for (DateTime dateTime : dateTimes) {
                    //天
                    String dateStr = DateUtil.format(dateTime, "yyyyMMdd");
                    String dateDd = DateUtil.format(dateTime, "dd");
                    MeetingRoomMonthVo.SingleCellVo singleCellVo = new MeetingRoomMonthVo.SingleCellVo();
                    singleCellVo.setDay(dateDd);
                    singleCellVo.setRealMeetingList(meetingAppMap.get(Integer.valueOf(dateStr)));
                    singleCellVoList.add(singleCellVo);
                }
                meetingRoomMonthVo.setSingleCellList(singleCellVoList);
                return meetingRoomMonthVo;

            }).collect(Collectors.toList());

        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public boolean apply(MeetingRoomApplyVo meetingRoomApplyVo) {
        MeetingRoom meetingRoom = this.selectById(meetingRoomApplyVo.getMeetingRoomId());
        AssertUtil.notNull(meetingRoom, "此会议室不存在或者已被删除");
        //预约时间段
        List<Integer> h = meetingRoomApplyVo.getHour();
        //查询这天的预约记录
        List<MeetingAppointmentVo> meetingAppointmentVos = meetingAppointmentService.selectList(MeetingAppointmentSearchVo.builder().roomId(meetingRoomApplyVo.getMeetingRoomId()).date(meetingRoomApplyVo.getDay()).build());
        if (CollectionUtil.isNotEmpty(meetingAppointmentVos)) {
            List<Integer> result = Lists.newArrayList();
            meetingAppointmentVos.forEach(meetingAppointmentVo -> {
                //预约时间段，多个
                String hour = meetingAppointmentVo.getHour();
                List<Integer> o = Arrays.stream(hour.split(",")).map(Integer::valueOf).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(o)) {
                    result.addAll(o);
                }
            });
            if (CollectionUtil.isNotEmpty(result)) {
                for (Integer hour : h) {
                    for (Integer r : result) {
                        AssertUtil.check(Objects.equals(hour, r), "有时间段已经被预约");
                    }
                }
            }
        }
        MeetingAppointment meetingAppointment = new MeetingAppointment();
        meetingAppointment.setRoomId(meetingRoomApplyVo.getMeetingRoomId());
        meetingAppointment.setDate(meetingRoomApplyVo.getDay());
        //第一
        Integer first = h.get(0);
        if (h.size() == 1) {
            //只有一个的话
            MeetingRoomHourEnum meetingRoomHourEnum = MeetingRoomHourEnum.getByCode(first);
            if (Objects.nonNull(meetingRoomHourEnum)) {
                meetingAppointment.setBetweenTime(meetingRoomHourEnum.getDesc());
            }
        } else {
            MeetingRoomHourEnum firstEnum = MeetingRoomHourEnum.getByCode(first);
            //最后
            Integer last = h.get(h.size() - 1);
            MeetingRoomHourEnum lastEnum = MeetingRoomHourEnum.getByCode(last);
            if (Objects.nonNull(firstEnum) && Objects.nonNull(lastEnum)) {
                String s = firstEnum.getDesc().split("-")[0];
                String s1 = lastEnum.getDesc().split("-")[1];
                meetingAppointment.setBetweenTime(String.format("%s-%s", s, s1));
            }
        }
        meetingAppointment.setApplyUserId(meetingRoomApplyVo.getUserId());
        meetingAppointment.setHour(StrUtil.joinInteger(",", meetingRoomApplyVo.getHour()));
        meetingAppointment.setApplyUserName(meetingRoomApplyVo.getApplyUserName());
        meetingAppointment.setApplyUserPhone(meetingRoomApplyVo.getApplyUserPhone());
        meetingAppointment.setMeetingName(meetingRoomApplyVo.getMeetingName());
        meetingAppointment.setMeetingType(meetingRoomApplyVo.getMeetingType());
        return meetingAppointmentService.insert(meetingAppointment) != 0;
    }

    @Override
    public boolean applyWithMeeting(MeetingRoomApplyVo meetingRoomApplyVo) {
        MeetingRoom meetingRoom = this.selectById(meetingRoomApplyVo.getMeetingRoomId());
        AssertUtil.notNull(meetingRoom, "此会议室不存在或者已被删除");
        //预约时间段
        List<Integer> h = meetingRoomApplyVo.getHour();
        //查询这天的预约记录
        Integer day = meetingRoomApplyVo.getDay();
        List<MeetingAppointmentVo> meetingAppointmentVos = meetingAppointmentService.selectList(MeetingAppointmentSearchVo.builder().roomId(meetingRoomApplyVo.getMeetingRoomId()).date(day).build());
        if (CollectionUtil.isNotEmpty(meetingAppointmentVos)) {
            List<Integer> result = Lists.newArrayList();
            meetingAppointmentVos.forEach(meetingAppointmentVo -> {
                //预约时间段，多个
                String hour = meetingAppointmentVo.getHour();
                List<Integer> o = Arrays.stream(hour.split(",")).map(Integer::valueOf).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(o)) {
                    result.addAll(o);
                }
            });
            if (CollectionUtil.isNotEmpty(result)) {
                for (Integer hour : h) {
                    for (Integer r : result) {
                        AssertUtil.check(Objects.equals(hour, r), "有时间段已经被预约");
                    }
                }
            }
        }
        MeetingAppointment meetingAppointment = new MeetingAppointment();
        meetingAppointment.setRoomId(meetingRoomApplyVo.getMeetingRoomId());
        meetingAppointment.setDate(day);
        //第一
        Integer first = h.get(0);
        if (h.size() == 1) {
            //只有一个的话
            MeetingRoomHourEnum meetingRoomHourEnum = MeetingRoomHourEnum.getByCode(first);
            if (Objects.nonNull(meetingRoomHourEnum)) {
                meetingAppointment.setBetweenTime(meetingRoomHourEnum.getDesc());
            }
        } else {
            MeetingRoomHourEnum firstEnum = MeetingRoomHourEnum.getByCode(first);
            //最后
            Integer last = h.get(h.size() - 1);
            MeetingRoomHourEnum lastEnum = MeetingRoomHourEnum.getByCode(last);
            if (Objects.nonNull(firstEnum) && Objects.nonNull(lastEnum)) {
                String s = firstEnum.getDesc().split("-")[0];
                String s1 = lastEnum.getDesc().split("-")[1];
                meetingAppointment.setBetweenTime(String.format("%s-%s", s, s1));
            }
        }
        meetingAppointment.setApplyUserId(meetingRoomApplyVo.getUserId());
        meetingAppointment.setHour(StrUtil.joinInteger(",", meetingRoomApplyVo.getHour()));
        meetingAppointment.setApplyUserName(meetingRoomApplyVo.getApplyUserName());
        meetingAppointment.setApplyUserPhone(meetingRoomApplyVo.getApplyUserPhone());
        meetingAppointment.setMeetingName(meetingRoomApplyVo.getMeetingName());
        meetingAppointment.setMeetingType(meetingRoomApplyVo.getMeetingType());
        meetingAppointment.setTeacher(meetingRoomApplyVo.getTeacher());
        boolean b = meetingAppointmentService.insert(meetingAppointment) != 0;
        if (b) {
            MeetingDataNewSaveOrUpdateVo meetingDataNewSaveOrUpdateVo = new MeetingDataNewSaveOrUpdateVo();
            meetingDataNewSaveOrUpdateVo.setAddress(meetingRoom.getName());
            DateTime dayDate = DateUtil.parse(day + "", FastDateFormat.getInstance("yyyyMMdd"));
            meetingDataNewSaveOrUpdateVo.setDate(DateUtil.formatDate(dayDate));
            meetingDataNewSaveOrUpdateVo.setType(meetingRoomApplyVo.getMeetingType());
            meetingDataNewSaveOrUpdateVo.setTime(meetingAppointment.getBetweenTime().split("-")[0]);
            meetingDataNewSaveOrUpdateVo.setTitle(meetingRoomApplyVo.getMeetingName());
            meetingDataNewSaveOrUpdateVo.setTeacher(meetingRoomApplyVo.getTeacher());
            meetingDataNewSaveOrUpdateVo.setUserName(meetingRoomApplyVo.getApplyUserName());
            meetingDataNewService.saveWithoutApply(meetingDataNewSaveOrUpdateVo);
        }
        return b;
    }

    @Override
    public MeetingRoomVo selectByName(String name) {
        return mapper.selectByName(name);
    }

    @Override
    public boolean updateMeeting(MeetingRoomApplyVo meetingRoomApplyVo) {
        MeetingAppointment meetingAppointment = meetingAppointmentService.selectById(meetingRoomApplyVo.getId());
        AssertUtil.notNull(meetingAppointment, "此记录不存在或者已被删除");
        MeetingRoom meetingRoom = this.selectById(meetingRoomApplyVo.getMeetingRoomId());
        AssertUtil.notNull(meetingRoom, "此会议室不存在或者已被删除");
        //预约时间段
        List<Integer> h = meetingRoomApplyVo.getHour();
        //查询这天的预约记录
        List<MeetingAppointmentVo> meetingAppointmentVos = meetingAppointmentService.selectList(MeetingAppointmentSearchVo.builder().notId(meetingRoomApplyVo.getId()).roomId(meetingRoomApplyVo.getMeetingRoomId()).date(meetingRoomApplyVo.getDay()).build());
        if (CollectionUtil.isNotEmpty(meetingAppointmentVos)) {
            List<Integer> result = Lists.newArrayList();
            meetingAppointmentVos.forEach(meetingAppointmentVo -> {
                //预约时间段，多个
                String hour = meetingAppointmentVo.getHour();
                List<Integer> o = Arrays.stream(hour.split(",")).map(Integer::valueOf).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(o)) {
                    result.addAll(o);
                }
            });
            if (CollectionUtil.isNotEmpty(result)) {
                for (Integer hour : h) {
                    for (Integer r : result) {
                        AssertUtil.check(Objects.equals(hour, r), "有时间段已经被预约");
                    }
                }
            }
        }
        meetingAppointment.setRoomId(meetingRoomApplyVo.getMeetingRoomId());
        meetingAppointment.setDate(meetingRoomApplyVo.getDay());
        //第一
        Integer first = h.get(0);
        if (h.size() == 1) {
            //只有一个的话
            MeetingRoomHourEnum meetingRoomHourEnum = MeetingRoomHourEnum.getByCode(first);
            if (Objects.nonNull(meetingRoomHourEnum)) {
                meetingAppointment.setBetweenTime(meetingRoomHourEnum.getDesc());
            }
        } else {
            MeetingRoomHourEnum firstEnum = MeetingRoomHourEnum.getByCode(first);
            //最后
            Integer last = h.get(h.size() - 1);
            MeetingRoomHourEnum lastEnum = MeetingRoomHourEnum.getByCode(last);
            if (Objects.nonNull(firstEnum) && Objects.nonNull(lastEnum)) {
                String s = firstEnum.getDesc().split("-")[0];
                String s1 = lastEnum.getDesc().split("-")[1];
                meetingAppointment.setBetweenTime(String.format("%s-%s", s, s1));
            }
        }
        meetingAppointment.setApplyUserId(meetingRoomApplyVo.getUserId());
        meetingAppointment.setHour(StrUtil.joinInteger(",", meetingRoomApplyVo.getHour()));
        meetingAppointment.setApplyUserName(meetingRoomApplyVo.getApplyUserName());
        meetingAppointment.setApplyUserPhone(meetingRoomApplyVo.getApplyUserPhone());
        meetingAppointment.setMeetingName(meetingRoomApplyVo.getMeetingName());
        meetingAppointment.setMeetingType(meetingRoomApplyVo.getMeetingType());
        return meetingAppointmentService.update(meetingAppointment);
    }

}